﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ComputerResourceConsole.lib;
using ComputerResourceConsole.common;
using ComputerResourceConsole.factory;
using NGIS.Model;
using System.IO;

namespace ComputerResourceConsole.control
{
    public struct DataConfig
    {
        public string StateName;
        public string EventName;
        public bool Optional;
        public string DataPath;

        public DataConfig(string stateName, string eventName, bool optional, string dataConfig)
        {
            this.StateName = stateName;
            this.EventName = eventName;
            this.Optional = optional;
            this.DataPath = dataConfig;
        }
    }

    public class ModelServiceDebuggerControl: ComponentControl, IModelServiceDebuggerControl
    {
        private IModelServiceDebuggerOpera _msDebuggerOpera = null;
        private ModelClass _mdl = null;
        private List<DataConfig> _dataConfig = null;

        public ModelServiceDebuggerControl():base()
        {
            this._msDebuggerOpera = ComponentOperaFactory.createModelServiceDebuggerOpera();
            this._dataConfig = new List<DataConfig>();
            this._msDebuggerOpera.FilePath = "GeoModelServiceContainer/debug_node.exe";
        }

        public int start(CommonMethod.CommonEvent exit)
        {
            this._status = "Started";
            return this._msDebuggerOpera.start(exit);
        }

        public int stop()
        {
            this._status = "Stopped";
            return this._msDebuggerOpera.stop();
        }

        public int restart(CommonMethod.CommonEvent exit)
        {
            this._msDebuggerOpera.stop();
            int flag = this._msDebuggerOpera.start(exit);
            this._status = "Started";
            return flag;
        }

        public bool loadMDLFile(string mdlPath)
        {
            try
            {
                this._mdl = new ModelClass();
                this._mdl.LoadFromXmlFile(mdlPath);
                this._msDebuggerOpera.MDLPath = mdlPath;
            }
            catch (Exception ex)
            {
                this._mdl = null;
                throw ex;
            }
            return true;
        }

        public NGIS.Model.IModelBehavior getModelBehavior()
        {
            if (this._mdl != null)
            {
                return this._mdl.getModelBehavior();
            }
            return null;
        }

        public string getMDLModelName()
        {
            if (this._mdl != null)
            {
                return this._mdl.getName();
            }
            return "";
        }

        public string getMDLModelUID()
        {
            if (this._mdl != null)
            {
                return this._mdl.getUID();
            }
            return "";
        }

        public string getMDLCategory()
        {
            if (this._mdl != null)
            {
                IModelAttribute pAttr = this._mdl.getModelAttribute();
                ModelCategory category = new ModelCategory();
                int count = pAttr.getCategoryCount();
                if (count > 0)
                {
                    pAttr.getCategory(0, ref category);
                    return category.principle + " - " + category.path;
                }
            }
            return "";
        }

        public void pushData(string stateName, string eventName, bool optional, string dataPath)
        {
            this._dataConfig.Add(new DataConfig(stateName, eventName, optional, dataPath));
        }

        public bool removeData(string stateName, string eventName)
        {
            for (int i = 0; i < this._dataConfig.Count; i++)
            {
                if (this._dataConfig[i].StateName == stateName && this._dataConfig[i].EventName == eventName)
                {
                    this._dataConfig.RemoveAt(i);
                    return true;
                }
            } 
            return true;
        }
        public int getDataIndex(string stateName, string eventName)
        {
            for (int i = 0; i < this._dataConfig.Count; i++)
            {
                if (this._dataConfig[i].StateName == stateName && this._dataConfig[i].EventName == eventName)
                {
                    return i;
                }
            }
            return -1;
        }

        public string getData(string stateName, string eventName)
        {
            int index = this.getDataIndex(stateName, eventName);
            if (index > -1)
            {
                return this._dataConfig[index].DataPath;
            }
            return "";
        }

        public int getDataCount()
        {
            return this._dataConfig.Count;
        }

        public bool updateData(string stateName, string eventName, string dataPath)
        {
            int index = this.getDataIndex(stateName, eventName);
            if (index > -1)
            {
                this._dataConfig[index] = new DataConfig(this._dataConfig[index].StateName, this._dataConfig[index].EventName, this._dataConfig[index].Optional, dataPath);
                return true;
            }
            return false;
        }

        public bool clearAllData()
        {
            this._dataConfig = new List<DataConfig>();
            return true;
        }

        public bool formatToFile(string filePath)
        {
            FileStream fs = new FileStream(filePath, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs);

            for (int i = 0; i < this._dataConfig.Count; i++)
            {
                sw.WriteLine(this._dataConfig[i].StateName + "\t" + this._dataConfig[i].EventName + "\t" + this._dataConfig[i].DataPath);
            }

            sw.Close();
            sw.Dispose();

            fs.Close();
            fs.Dispose();

            return true;
        }

        public bool formatToFile()
        {
            if (this._msDebuggerOpera.DataConfigPath == "")
            {
                return false;
            }
            return this.formatToFile(this._msDebuggerOpera.DataConfigPath);
        }

        public bool MDLLoading
        {
            get 
            {
                if (this._mdl == null)
                {
                    return false;
                }
                return true;
            }
        }

        public bool DataReady
        {
            get 
            {
                for (int i = 0; i < this._dataConfig.Count; i++)
                {
                    if (!this._dataConfig[i].Optional && this._dataConfig[i].DataPath == "")
                    {
                        return false;
                    }
                }
                return true;
            }
        }

        public bool DirectoryReady
        {
            get 
            {
                try
                {
                    string path = CommonMethod.getAppDirection() +  _pConfig.NodejsPath + "/../geo_model/DebugModel/";
                    if (!System.IO.Directory.Exists(path))
                    {
                        System.IO.Directory.CreateDirectory(path);
                    }
                    path += "instance/";
                    if (!System.IO.Directory.Exists(path))
                    {
                        System.IO.Directory.CreateDirectory(path);
                    }
                    this._msDebuggerOpera.DataConfigPath = path + "data.config";
                    return true;
                }
                catch (Exception ex)
                {
                    return false;
                }

            }
        }

        public string Host
        {
            get
            {
                return this._msDebuggerOpera.Host;
            }
            set
            {
                this._msDebuggerOpera.Host = value;
            }
        }

        public int Port
        {
            get
            {
                return this._msDebuggerOpera.Port;
            }
            set
            {
                this._msDebuggerOpera.Port = value;
            }
        }


        public string InstanceID
        {
            get
            {
                return this._msDebuggerOpera.InstanceID;
            }
            set
            {
                this._msDebuggerOpera.InstanceID = value;
            }
        }
    }
}
